Support new xm command: xm trigger <Domain> <nmi|reset|init> [<VCPU>]
authorKeir Fraser <keir@xensource.com>
Sat, 24 Feb 2007 14:10:27 +0000 (14:10 +0000)
committerKeir Fraser <keir@xensource.com>
Sat, 24 Feb 2007 14:10:27 +0000 (14:10 +0000)
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
Signed-off-by: Zhang Xin <xing.z.zhang@intel.com>
13 files changed:
linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendConstants.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xm/main.py
xen/arch/ia64/vmx/vlsapic.c
xen/arch/ia64/vmx/vmx_process.c
xen/arch/ia64/xen/dom0_ops.c
xen/include/asm-ia64/vmx.h
xen/include/asm-ia64/vmx_vpd.h
xen/include/public/domctl.h

index 0f5fccdac749e7faa157a8b41a3548cc013cde03..e1e312d204f5da4e4bebda070fec2b4d1e0c4640 100644 (file)
@@ -303,6 +303,7 @@ xencomm_privcmd_domctl(privcmd_hypercall_t *hypercall)
        case XEN_DOMCTL_hypercall_init:
        case XEN_DOMCTL_arch_setup:
        case XEN_DOMCTL_settimeoffset:
+       case XEN_DOMCTL_sendtrigger:
                break;
        default:
                printk("%s: unknown domctl cmd %d\n", __func__, kern_op.cmd);
index 6e3b0d9e8267b28d58f9ada150b007b2f85aed9a..1b6962d54dea5d2408bdaaf5c08785752985a0cb 100644 (file)
@@ -642,6 +642,21 @@ int xc_domain_iomem_permission(int xc_handle,
     return do_domctl(xc_handle, &domctl);
 }
 
+int xc_domain_send_trigger(int xc_handle,
+                           uint32_t domid,
+                           uint32_t trigger,
+                           uint32_t vcpu)
+{
+    DECLARE_DOMCTL;
+
+    domctl.cmd = XEN_DOMCTL_sendtrigger;
+    domctl.domain = domid;
+    domctl.u.sendtrigger.trigger = trigger;
+    domctl.u.sendtrigger.vcpu = vcpu;
+
+    return do_domctl(xc_handle, &domctl);
+}
+
 /*
  * Local variables:
  * mode: C
index 14704e2e92435d9b6b873712bb11bb8a16c92efe..3f60fdff13a208319e35296bf3b5aa989612b977 100644 (file)
@@ -414,6 +414,20 @@ int xc_sched_credit_domain_get(int xc_handle,
                                uint32_t domid,
                                struct xen_domctl_sched_credit *sdom);
 
+/**
+ * This function sends a trigger to a domain.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain id to send trigger
+ * @parm trigger the trigger type
+ * @parm vcpu the vcpu number to send trigger 
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_send_trigger(int xc_handle,
+                           uint32_t domid,
+                           uint32_t trigger,
+                           uint32_t vcpu);
+
 /*
  * EVENT CHANNEL FUNCTIONS
  */
index 792f57f7d488f79bfa6a15a229835451c7304dea..9b11b3c5f415e58ac5bd23929921833eefcb0e17 100644 (file)
@@ -936,6 +936,26 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args)
     return zero;
 }
 
+static PyObject *pyxc_domain_send_trigger(XcObject *self,
+                                          PyObject *args,
+                                          PyObject *kwds)
+{
+    uint32_t dom;
+    int trigger, vcpu = 0;
+
+    static char *kwd_list[] = { "domid", "trigger", "vcpu", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|i", kwd_list, 
+                                      &dom, &trigger, &vcpu) )
+        return NULL;
+
+    if (xc_domain_send_trigger(self->xc_handle, dom, trigger, vcpu) != 0)
+        return pyxc_error_to_exception();
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 static PyObject *dom_op(XcObject *self, PyObject *args,
                         int (*fn)(int, uint32_t))
 {
@@ -1339,6 +1359,15 @@ static PyMethodDef pyxc_methods[] = {
       " dom        [int]: Domain whose time offset is being set.\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
+    { "domain_send_trigger",
+      (PyCFunction)pyxc_domain_send_trigger,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Send trigger to a domain.\n"
+      " dom     [int]: Identifier of domain to be sent trigger.\n"
+      " trigger [int]: Trigger type number.\n"
+      " vcpu    [int]: VCPU to be sent trigger.\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
 #ifdef __powerpc__
     { "arch_alloc_real_mode_area", 
       (PyCFunction)pyxc_alloc_real_mode_area, 
index e42216d06b43c9890c6dff5bae4a21d60d9a3ffb..e6bc7873403e8468748dc59bafae5e4b0c3b6b1a 100644 (file)
@@ -82,6 +82,16 @@ MINIMUM_RESTART_TIME = 20
 RESTART_IN_PROGRESS = 'xend/restart_in_progress'
 LAST_SHUTDOWN_REASON = 'xend/last_shutdown_reason'
 
+TRIGGER_NMI   = 0
+TRIGGER_RESET = 1
+TRIGGER_INIT  = 2
+
+TRIGGER_TYPE = {
+    "nmi"   : TRIGGER_NMI,
+    "reset" : TRIGGER_RESET,
+    "init"  : TRIGGER_INIT
+}
+
 #
 # Device migration stages (eg. XendDomainInfo, XendCheckpoint, server.tpmif)
 #
index 0c8cddde48eae0ce454849b28e40723351862b28..fbb66e1461cb0050a153dc79a62df6a741df8d3a 100644 (file)
@@ -43,6 +43,7 @@ from xen.xend.XendConstants import XS_VMROOT
 from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_PAUSED
 from xen.xend.XendConstants import DOM_STATE_RUNNING, DOM_STATE_SUSPENDED
 from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN
+from xen.xend.XendConstants import TRIGGER_TYPE
 from xen.xend.XendDevices import XendDevices
 
 from xen.xend.xenstore.xstransact import xstransact
@@ -1433,6 +1434,33 @@ class XendDomain:
         except Exception, ex:
             raise XendError(str(ex))
 
+    def domain_send_trigger(self, domid, trigger_name, vcpu = 0):
+        """Send trigger to a domain.
+
+        @param domid: Domain ID or Name
+        @type domid: int or string.
+        @param trigger_name: trigger type name
+        @type trigger_name: string
+        @param vcpu: VCPU to send trigger (default is 0) 
+        @type vcpu: int
+        @raise XendError: failed to send trigger
+        @raise XendInvalidDomain: Domain is not valid        
+        @rtype: 0
+        """
+        dominfo = self.domain_lookup_nr(domid)
+        if not dominfo:
+            raise XendInvalidDomain(str(domid))
+        if trigger_name.lower() in TRIGGER_TYPE: 
+            trigger = TRIGGER_TYPE[trigger_name.lower()]
+        else:
+            raise XendError("Invalid trigger: %s", trigger_name)
+        try:
+            return xc.domain_send_trigger(dominfo.getDomid(),
+                                          trigger,
+                                          vcpu)
+        except Exception, ex:
+            raise XendError(str(ex))
 
 def instance():
     """Singleton constructor. Use this instead of the class constructor.
index 7635b06c919a402133f94444602ccbe14ec70d55..ea52f0244d03151b00af89152b1482db4efeb648 100644 (file)
@@ -133,6 +133,8 @@ SUBCOMMAND_HELP = {
     'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
                      'Get/set credit scheduler parameters.'),
     'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
+    'trigger'     : ('<Domain> <nmi|reset|init> [<VCPU>]',
+                     'Send a trigger to a domain.'),
     'vcpu-list'   : ('[<Domain>]',
                      'List the VCPUs for a domain or all domains.'),
     'vcpu-pin'    : ('<Domain> <VCPU> <CPUs>',
@@ -255,6 +257,7 @@ common_commands = [
     "shutdown",
     "start",
     "suspend",
+    "trigger",
     "top",
     "unpause",
     "uptime",
@@ -284,6 +287,7 @@ domain_commands = [
     "start",
     "suspend",
     "sysrq",
+    "trigger",
     "top",
     "unpause",
     "uptime",
@@ -1347,6 +1351,17 @@ def xm_sysrq(args):
     req = args[1]
     server.xend.domain.send_sysrq(dom, req)    
 
+def xm_trigger(args):
+    vcpu = 0
+    
+    arg_check(args, "trigger", 2, 3)
+    dom = args[0]
+    trigger = args[1]
+    if len(args) == 3:
+        vcpu = int(args[2])
+    
+    server.xend.domain.send_trigger(dom, trigger, vcpu)
+
 def xm_top(args):
     arg_check(args, "top", 0)
 
@@ -1668,6 +1683,7 @@ commands = {
     "shutdown": xm_shutdown,
     "start": xm_start,
     "sysrq": xm_sysrq,
+    "trigger": xm_trigger,
     "uptime": xm_uptime,
     "suspend": xm_suspend,
     "list": xm_list,
index 81b1fd46d981aef8df7e3ece7ee9872978237e84..a6d0a64c8a8065934cab15e594b7c81e5a8da393 100644 (file)
@@ -497,6 +497,18 @@ chk_irq_exit:
     return h_pending;
 }
 
+/*
+ * Set a INIT interruption request to vcpu[0] of target domain.
+ * The INIT interruption is injected into each vcpu by guest firmware.
+ */
+void vmx_pend_pal_init(struct domain *d)
+{
+    VCPU *vcpu;
+
+    vcpu = d->vcpu[0];
+    vcpu->arch.arch_vmx.pal_init_pending = 1;
+}
+
 /*
  * Only coming from virtualization fault.
  */
@@ -643,6 +655,14 @@ static void vlsapic_deliver_ipi(VCPU *vcpu, uint64_t dm, uint64_t vector)
     }
 }
 
+/*
+ * Deliver the INIT interruption to guest.
+ */
+void deliver_pal_init(VCPU *vcpu)
+{
+    vlsapic_deliver_ipi(vcpu, SAPIC_INIT, 0);
+}
+
 /*
  * TODO: Use hash table for the lookup.
  */
index be49be865358835dc5c8b83d1b22c48b991d0b60..5e40330476b2fd65599d3636491f12de5e3c9f57 100644 (file)
@@ -229,6 +229,14 @@ void leave_hypervisor_tail(void)
         if (v->vcpu_id == 0) {
             unsigned long callback_irq =
                 d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
+
+            if ( v->arch.arch_vmx.pal_init_pending ) {
+                /*inject INIT interruption to guest pal*/
+                v->arch.arch_vmx.pal_init_pending = 0;
+                deliver_pal_init(v);
+                return;
+            }
+
             /*
              * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
              *                  Domain = val[47:32], Bus  = val[31:16],
index 52c3745f8795fba9f7cc5baaa2fdff29c059f5e6..b23d222e84b3164b80ac0423e129ad87df885020 100644 (file)
@@ -174,6 +174,46 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         put_domain(d);
     }
     break;
+
+    case XEN_DOMCTL_sendtrigger:
+    {
+        struct domain *d;
+        struct vcpu *v;
+
+        ret = -ESRCH;
+        d = get_domain_by_id(op->domain);
+        if ( d == NULL )
+            break;
+
+        ret = -EINVAL;
+        if ( op->u.sendtrigger.vcpu >= MAX_VIRT_CPUS )
+            goto sendtrigger_out;
+
+        ret = -ESRCH;
+        if ( (v = d->vcpu[op->u.sendtrigger.vcpu]) == NULL )
+            goto sendtrigger_out;
+
+        ret = 0;
+        switch (op->u.sendtrigger.trigger)
+        {
+        case XEN_DOMCTL_SENDTRIGGER_INIT:
+        {
+            if (VMX_DOMAIN(v))
+                vmx_pend_pal_init(d);
+            else
+                ret = -ENOSYS;
+        }
+        break;
+
+        default:
+            ret = -ENOSYS;
+        }
+
+    sendtrigger_out:
+        put_domain(d);
+    }
+    break;
+
     default:
         printk("arch_do_domctl: unrecognized domctl: %d!!!\n",op->cmd);
         ret = -ENOSYS;
index 3487888daf7c143d560e5aaa8da8d9931e8a034e..6bf682dbf0fad639aefc0516a703dd5647811208 100644 (file)
@@ -54,6 +54,8 @@ extern void vmx_relinquish_guest_resources(struct domain *d);
 extern void vmx_relinquish_vcpu_resources(struct vcpu *v);
 extern void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err);
 extern void vmx_send_assist_req(struct vcpu *v);
+extern void deliver_pal_init(struct vcpu *vcpu);
+extern void vmx_pend_pal_init(struct domain *d);
 
 static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
 {
index e8876bb1544eea14755e9861c30f53812a7fc299..85bd0b1b0bdcdc1ce9fb0d54ecc75d54cfd4b22e 100644 (file)
@@ -90,6 +90,7 @@ struct arch_vmx_struct {
     unsigned long   flags;
     unsigned long   xen_port;
     unsigned char   xtp;
+    unsigned char   pal_init_pending;
 #ifdef VTI_DEBUG
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];
index f7ea2d8accdebf0fcbda783886a83ab13534b12f..ce7bc480a96adc827595441986f4bf69135cd277 100644 (file)
@@ -356,6 +356,7 @@ struct xen_domctl_ioport_permission {
 typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
 
+
 #define XEN_DOMCTL_hypercall_init    22
 struct xen_domctl_hypercall_init {
     uint64_aligned_t  gmfn;           /* GMFN to be initialised */
@@ -363,6 +364,7 @@ struct xen_domctl_hypercall_init {
 typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
 
+
 #define XEN_DOMCTL_arch_setup        23
 #define _XEN_DOMAINSETUP_hvm_guest 0
 #define XEN_DOMAINSETUP_hvm_guest  (1UL<<_XEN_DOMAINSETUP_hvm_guest)
@@ -379,15 +381,17 @@ typedef struct xen_domctl_arch_setup {
 } xen_domctl_arch_setup_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t);
 
+
 #define XEN_DOMCTL_settimeoffset     24
 struct xen_domctl_settimeoffset {
     int32_t  time_offset_seconds; /* applied to domain wallclock time */
 };
 typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
+
  
-#define XEN_DOMCTL_gethvmcontext   33
-#define XEN_DOMCTL_sethvmcontext   34
+#define XEN_DOMCTL_gethvmcontext     33
+#define XEN_DOMCTL_sethvmcontext     34
 typedef struct xen_domctl_hvmcontext {
     uint32_t size; /* IN/OUT: size of buffer / bytes filled */
     XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext 
@@ -395,20 +399,35 @@ typedef struct xen_domctl_hvmcontext {
 } xen_domctl_hvmcontext_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
 
-#define XEN_DOMCTL_set_address_size 35
-#define XEN_DOMCTL_get_address_size 36
+
+#define XEN_DOMCTL_set_address_size  35
+#define XEN_DOMCTL_get_address_size  36
 typedef struct xen_domctl_address_size {
     uint32_t size;
 } xen_domctl_address_size_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
 
-#define XEN_DOMCTL_real_mode_area     26
+
+#define XEN_DOMCTL_real_mode_area    26
 struct xen_domctl_real_mode_area {
     uint32_t log; /* log2 of Real Mode Area size */
 };
 typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
 
+
+#define XEN_DOMCTL_sendtrigger       28
+#define XEN_DOMCTL_SENDTRIGGER_NMI    0
+#define XEN_DOMCTL_SENDTRIGGER_RESET  1
+#define XEN_DOMCTL_SENDTRIGGER_INIT   2
+struct xen_domctl_sendtrigger {
+    uint32_t  trigger;  /* IN */
+    uint32_t  vcpu;     /* IN */
+};
+typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
+
 struct xen_domctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -437,6 +456,7 @@ struct xen_domctl {
         struct xen_domctl_real_mode_area    real_mode_area;
         struct xen_domctl_hvmcontext        hvmcontext;
         struct xen_domctl_address_size      address_size;
+        struct xen_domctl_sendtrigger       sendtrigger;
         uint8_t                             pad[128];
     } u;
 };